/* udp-broadcast-client.c
 * udp datagram client
 * Get datagram stock market quotes from UDP broadcast:
 * see below the step by step explanation
 */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

extern int mkaddr(
	void *addr,
	int *addrlen,
	char *str_addr,
	char *protocol);

/*
 * This function reports the error and
 * exits back to the shell:
 */
static void
displayError(const char *on_what) {
	fputs(strerror(errno),stderr);
	fputs(": ",stderr);
	fputs(on_what,stderr);
	fputc('\n',stderr);
	exit(1);
}

void get_netmask(int socket, char *intf, char *netmask, int bufsize)
{
	struct ifreq ifr;
	memset(&ifr, 0, sizeof(ifr));
	struct sockaddr_in *ifr_netmaskp = (struct sockaddr_in *)&ifr.ifr_netmask;
	strcpy(ifr.ifr_name, intf);
	if(ioctl(socket, SIOCGIFNETMASK, &ifr) == -1) {
		printf("failed\n");
		exit(0);
	}
	inet_ntop(AF_INET, &ifr_netmaskp->sin_addr, netmask, bufsize);
}

void set_netmask( int skfd, char *intf, char *newmask )
{
    struct ifreq ifr;
    unsigned int dst;
    struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr;
    memset(&ifr, 0, sizeof(ifr));
    sin->sin_family = AF_INET;
    if ( !inet_pton(AF_INET, newmask, &sin->sin_addr) )
    {
        printf("failed to convert netmask\n");
        exit( 0 );
    }
    strncpy( ifr.ifr_name, intf, IFNAMSIZ-1 );
    if ( ioctl(skfd,SIOCSIFNETMASK,&ifr) == -1 )
    {
        printf("could not read interface %s\n",intf);
        exit( 0 );
    }
}
int main(int argc,char **argv) 
{
	int z;
	int x;
	int len_inet;            /* length */
	int s;                   /* Socket */
	char dgram[512];         /* Recv buffer */

	static char *bc_addr = "192.168.1.255:9097";
	if ( argc > 1 )
		bc_addr = argv[1];

	/*
	 * Create a UDP socket to use:
	 */
	s = socket(AF_INET,SOCK_DGRAM,0);
	if ( s == -1 )
		displayError("socket()");

	struct sockaddr_in adr;
	len_inet = sizeof adr;

	z = mkaddr(&adr, &len_inet, bc_addr, "udp");
	if ( z == -1 )
		displayError("Bad broadcast address");

	static int so_reuseaddr = 1;
	z = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
		&so_reuseaddr, sizeof so_reuseaddr);

	static int so_broadcast = 1;
	z = setsockopt(s, SOL_SOCKET, SO_BROADCAST, 
		&so_broadcast, sizeof so_broadcast);
	if ( z == -1 )
		displayError("setsockopt(SO_REUSEADDR)");

	/*  
	static char *interface = "lo";
	char netmask[INET_ADDRSTRLEN] = {0};
	get_netmask(s,interface, netmask, INET_ADDRSTRLEN);
	printf("interface:%s, netmask:%s\n", interface, netmask);
	if(strcmp(netmask, "255.255.255.0") != 0)
		set_netmask(s, interface, "255.255.255.0");
	*/


	printf("addr:%s,port:%d\n", inet_ntoa(adr.sin_addr), ntohs(adr.sin_port));
	z = bind(s, (struct sockaddr *)&adr, len_inet);
	if ( z == -1 )
		displayError("bind(2)");

	for (;;) {
		printf("------------------------------\n");
		z = recvfrom(s, dgram, sizeof dgram, 0, (struct sockaddr *)&adr, &x);
		if ( z < 0 )
			displayError("recvfrom(2)");

		fwrite(dgram,z,1,stdout);
		putchar('\n');
		fflush(stdout);
	}

	return 0;
}

